<?php

namespace app\common\logic;

use app\common\library\enum\CodeEnum;
use think\Cache;
use think\Db;
use think\Log;

class Pay extends BaseLogic
{
    /**
     * 下单时通过pay_code 获取渠道下的可用商户配置.
     *
     *
     * @param $order
     *
     * @return mixed
     */
    public function getAllowedAccount($order)
    {
        //1.传入支付方式获取对应渠道cnl_id
        $codeInfo = $this->modelPayCode->getInfo(['name' => $order['channel']], 'id as co_id, cnl_id, code')->toArray();

        $cache = Cache::store('redis');
        $cache_key = 'PayCode:'.$order['channel'];
        $accountList = $cache->get($cache_key);
        if (!$accountList || count($accountList) <= 0) {
            //2.cnl_id获取支持该方式的渠道列表
            $channels = $this->modelPayChannel->getColumn(
                ['id' => ['in', $codeInfo['cnl_id']], 'status' => ['eq', '1']],
                'id,name,action,timeslot,return_url,notify_url'
            );

            //判断可用
            if (empty($channels)) {
                return ['errorCode' => '400006', 'msg' => 'Route Payment Error. [No available channels]'];
            }

            $channelsMap = [];
            foreach ($channels as $key => $val) {
                $channelsMap[$val['id']] = $val;
            }

            /*******************************/
            //3.获取该渠道下可用账户
            $channelIds = join(',', array_column($channels, 'id'));
            $accounts = $this->modelPayAccount->getColumn(
                ['cnl_id' => ['in', $channelIds], 'status' => ['eq', '1']],
                'cnl_id,co_id, id as account_id, name as account_name,single,daily,timeslot,param,account_use_type,account_use_threshold',
                'id'
            );

            //判断可用
            if (empty($accounts)) {
                return ['errorCode' => '400008', 'msg' => 'Route Payment Error. [No available account.]'];
            }

            $accountList = [];
            foreach ($accounts as $key => $val) {
                $accountConf = json_decode($val['param'], true);
                if (!is_null($accountConf)) {
                    $cnl_id = $val['cnl_id'];
                    unset($val['cnl_id']);
                    unset($val['timeslot']);
                    $val['account_use_current'] = 0;
                    $val = array_merge($val, $accountConf);
                    if ($val['account_use_current'] < $val['account_use_threshold']) {
                        $tmpAccount = array_merge($channelsMap[$cnl_id], $val);
                        $accountList[$tmpAccount['account_id']] = $tmpAccount;
                    }
                }
            }
            krsort($accountList);
            $cache->set($cache_key, $accountList);
        }

        $order_amt = $order['amount'];
        $account = [];
        foreach ($accountList as $key => $val) {
            if ($order_amt <= $val['single']) {
                if (1 == $val['account_use_type']) {
                    $val['account_use_current'] = bcadd($val['account_use_current'], 1);
                    $account = $val;
                    break;
                } elseif (2 == $val['account_use_type']) {
                    $val['account_use_current'] = bcadd($val['account_use_current'], $order_amt, 2);
                    $account = $val;
                    break;
                }
            }
        }

        //判断可用
        if (empty($account)) {
            return ['errorCode' => '400008', 'msg' => 'Route Payment Error. [No available account.]'];
        } else {
            if ($account['account_use_current'] >= $account['account_use_threshold']) {
                unset($accountList[$account['account_id']]);
                $cache->set($cache_key, $accountList);
            } else {
                $accountList[$account['account_id']] = $account;
                $cache->set($cache_key, $accountList);
            }
        }

        $accountConf = json_decode($account['param'], true);

        //添加订单支付通道ID
        $this->logicOrders->setOrderValue(['trade_no' => $order['trade_no']], 'cnl_id', $account['account_id']);

        return ['channel' => $account['action'], 'action' => $codeInfo['code'], 'config' => $account];

        // //1.传入支付方式获取对应渠道cnl_id
        // $codeInfo = $this->modelPayCode->getInfo(['code' => $order['channel']], 'id as co_id,cnl_id')->toArray();

        // //2.cnl_id获取支持该方式的渠道列表
        // $channels = $this->modelPayChannel->getColumn(
        //     ['id' => ['in', $codeInfo['cnl_id']], 'status' => ['eq', '1']],
        //     'id,name,action,timeslot,return_url,notify_url'
        // );

        // //3.规则排序选择合适渠道
        // /*******************************/
        // //TODO 写选择规则  时间、状态、费率 等等
        // //规则处理  我先简便写一下
        // $channelsMap = [];
        // foreach ($channels as $key => $val) {
        //     $timeslot = json_decode($val['timeslot'], true);
        //     if (strtotime($timeslot['start']) < time() && time() < strtotime($timeslot['end'])) {
        //         $channelsMap[$key] = $val;
        //     }
        // }

        // //判断可用
        // if (empty($channelsMap)) {
        //     return ['errorCode' => '400006', 'msg' => 'Route Payment Error. [No available channels]'];
        // }
        // $channel =  $channelsMap[array_rand($channelsMap)];

        // /*******************************/
        // //3.获取该渠道下可用账户
        // $accounts = $this->modelPayAccount->getColumn(
        //     ['cnl_id' => ['eq', $channel['id']], 'status' => ['eq', '1']],
        //     'id,co_id,name,single,daily,timeslot,param'
        // );

        // //4.规则取出可用账户
        // /*******************************/
        // //TODO 写选择规则  时间、状态、费率 等等
        // //规则处理  我先简便写一下
        // $accountsMap = [];
        // foreach ($accounts as $key => $val) {
        //     $timeslot = json_decode($val['timeslot'], true);
        //     // if ( in_array($codeInfo['co_id'], str2arr($val['co_id'])) && strtotime($timeslot['start']) < time() && time() < strtotime($timeslot['end']) ){
        //     $accountsMap[$key] = $val;
        //     // }
        // }

        // //判断可用
        // if (empty($accountsMap)) {
        //     return ['errorCode' => '400008', 'msg' => 'Route Payment Error. [No available merchants account.]'];
        // }

        // $account =  $accountsMap[array_rand($accountsMap)];
        // $accountConf = json_decode($account['param'], true);
        // //判断配置是否正确
        // if (is_null($accountConf)) {
        //     return ['errorCode' => '400008', 'msg' => 'Route Payment Error. [Payment account was misconfigured.]'];
        // }
        // //配置合并
        // $configMap = array_merge($channel, $accountConf);

        // //添加订单支付通道ID
        // $this->logicOrders->setOrderValue(['trade_no' => $order['trade_no']], 'cnl_id', $account['id']);

        //return ['channel' => $configMap['action'], 'action' => $order['channel'], 'config' =>  $configMap];
    }

    /**
     * 获取所有支持的支付方式.
     *
     *
     * @return mixed
     */
    public function getAppCodeMap()
    {
        return $this->modelPayCode->getColumn(['status' => 1], 'id,code', $key = 'id');
    }

    /**
     * 获取支付方式列表.
     *
     *
     * @param array $where
     * @param $field
     * @param string $order
     *
     * @return mixed
     */
    public function getCode($where = [])
    {
        return $this->modelPayCode->getInfo($where);
    }

    /**
     * 获取支付方式列表.
     *
     *
     * @param array $where
     * @param $field
     * @param string $order
     *
     * @return mixed
     */
    public function getCodeList($where = [], $field = true, $order = 'create_time desc', $paginate = 15)
    {
        return $this->modelPayCode->getList($where, $field, $order, $paginate);
    }

    /**
     * 获取支付方式总数.
     *
     *
     * @param $where
     *
     * @return mixed
     */
    public function getCodeCount($where = [])
    {
        return $this->modelPayCode->getCount($where);
    }

    /**
     * 获取渠道列表.
     *
     *
     * @param array $where
     * @param $field
     * @param string $order
     *
     * @return mixed
     */
    public function getChannelList($where = [], $field = true, $order = 'create_time desc', $paginate = 15)
    {
        return $this->modelPayChannel->getList($where, $field, $order, $paginate);
    }

    /**
     * 获取渠道总数.
     *
     *
     * @param $where
     *
     * @return mixed
     */
    public function getChannelCount($where = [])
    {
        return $this->modelPayChannel->getCount($where);
    }

    /**
     * 获取渠道账户列表.
     *
     *
     * @param array $where
     * @param $field
     * @param string $order
     *
     * @return mixed
     */
    public function getAccountList($where = [], $field = true, $order = 'create_time desc', $paginate = 15)
    {
        return $this->modelPayAccount->getList($where, $field, $order, $paginate);
    }

    /**
     * 获取渠道账户总数.
     *
     *
     * @param $where
     *
     * @return mixed
     */
    public function getAccountCount($where = [])
    {
        return $this->modelPayAccount->getCount($where);
    }

    /**
     * 获取渠道信息.
     *
     *
     * @param array $where
     * @param bool  $field
     *
     * @return mixed
     */
    public function getChannelInfo($where = [], $field = true)
    {
        return $this->modelPayChannel->getInfo($where, $field);
    }

    /**
     * 获取渠道账户信息.
     *
     *
     * @param array $where
     * @param bool  $field
     *
     * @return mixed
     */
    public function getAccountInfo($where = [], $field = true)
    {
        return $this->modelPayAccount->getInfo($where, $field);
    }

    /**
     * 获取支付方式信息.
     *
     *
     * @param array $where
     * @param bool  $field
     *
     * @return mixed
     */
    public function getCodeInfo($where = [], $field = true)
    {
        return $this->modelPayCode->getInfo($where, $field);
    }

    /**
     * 添加一个渠道.
     *
     *
     * @param $data
     *
     * @return array|string
     */
    public function saveChannelInfo($data)
    {
        $data['grate'] = 0;

        //TODO 数据验证
        $validate = $this->validatePayChannel->check($data);

        if (!$validate) {
            return ['code' => CodeEnum::ERROR,  'msg' => $this->validatePayChannel->getError()];
        }

        //TODO 添加数据
        Db::startTrans();
        try {
            //时间存储
            //$data['timeslot'] = json_encode($data['timeslot']);
            $data['timeslot'] = '{"start":"0:0","end":"24:00"}';

            $this->modelPayChannel->setInfo($data);

            $action = '新增';
            if (isset($data['id'])) {
                $this->modelPayAccount->updateInfo(['cnl_id' => $data['id']], ['urate' => $data['urate'], 'grate' => $data['grate']]);
                $action = '编辑';
            }

            $action = isset($data['id']) ? '编辑' : '新增';

            action_log($action, '支付渠道'.$data['name']);

            Db::commit();

            return ['code' => CodeEnum::SUCCESS,  'msg' => $action.'渠道成功'];
        } catch (\Exception $ex) {
            Db::rollback();
            Log::error($ex->getMessage());

            return ['code' => CodeEnum::ERROR,  'msg' => config('app_debug') ? $ex->getMessage() : '未知错误'];
        }
    }

    /**
     * 添加一个渠道账户.
     *
     *
     * @param $data
     *
     * @return array|string
     */
    public function saveAccountInfo($data)
    {
        $data['urate'] = 0;
        $data['grate'] = 0;
        $data['daily'] = 0;

        //TODO 数据验证
        $validate = $this->validatePayAccount->check($data);

        if (!$validate) {
            return ['code' => CodeEnum::ERROR,  'msg' => $this->validatePayAccount->getError()];
        }

        //TODO 添加数据
        Db::startTrans();
        try {
            $chanelInfo = $this->modelPayChannel->getInfo(['id' => $data['cnl_id']]);

            $data['urate'] = $chanelInfo['urate'];
            $data['grate'] = $chanelInfo['grate'];

            //时间存储
            //$data['timeslot'] = json_encode($data['timeslot']);
            $data['timeslot'] = '{"start":"0:0","end":"23:59"}';

            //方式存储
            $data['co_id'] = isset($data['co_id']) ? arr2str($data['co_id']) : '';

            $this->modelPayAccount->setInfo($data);

            $action = isset($data['id']) ? '编辑' : '新增';

            action_log($action, '支付渠道账户,'.$data['name']);

            Db::commit();

            return ['code' => CodeEnum::SUCCESS,  'msg' => $action.'渠道账户成功'];
        } catch (\Exception $ex) {
            Db::rollback();
            Log::error($ex->getMessage());

            return ['code' => CodeEnum::ERROR,  'msg' => config('app_debug') ? $ex->getMessage() : '未知错误'];
        }
    }

    /**
     * 添加一个方式.
     *
     *
     * @param $data
     *
     * @return array|string
     */
    public function saveCodeInfo($data)
    {
        //TODO 数据验证
        $validate = $this->validatePayCode->check($data);

        if (!$validate) {
            return ['code' => CodeEnum::ERROR,  'msg' => $this->validatePayCode->getError()];
        }
        //TODO 添加数据
        Db::startTrans();
        try {
            $data['cnl_id'] = isset($data['cnl_id']) ? arr2str($data['cnl_id']) : '';

            $this->modelPayCode->setInfo($data);

            $action = isset($data['id']) ? '编辑' : '新增';

            action_log($action, '支付方式,data:'.http_build_query($data));

            Db::commit();

            return ['code' => CodeEnum::SUCCESS, 'msg' => $action.'方式成功'];
        } catch (\Exception $ex) {
            Db::rollback();
            Log::error($ex->getMessage());

            return ['code' => CodeEnum::ERROR,  'msg' => config('app_debug') ? $ex->getMessage() : '未知错误'];
        }
    }

    /**
     * 改变渠道可用性.
     *
     *
     * @param $where
     * @param int $value
     *
     * @return array
     */
    public function setChannelStatus($where, $value = 0)
    {
        Db::startTrans();
        try {
            $this->modelPayChannel->setFieldValue($where, $field = 'status', $value);
            Db::commit();

            return ['code' => CodeEnum::SUCCESS, 'msg' => '修改状态成功'];
        } catch (\Exception $ex) {
            Db::rollback();
            Log::error($ex->getMessage());

            return ['code' => CodeEnum::ERROR,  'msg' => config('app_debug') ? $ex->getMessage() : '未知错误'];
        }
    }

    /**
     * 删除一个方式.
     *
     *
     * @param $where
     *
     * @return array
     */
    public function delCode($where)
    {
        Db::startTrans();
        try {
            $this->modelPayCode->deleteInfo($where);
            action_log('删除', '删除支付方式，ID：'.$where['id']);
            Db::commit();

            return ['code' => CodeEnum::SUCCESS, 'msg' => '删除方式成功'];
        } catch (\Exception $ex) {
            Db::rollback();
            Log::error($ex->getMessage());

            return ['code' => CodeEnum::ERROR,  'msg' => config('app_debug') ? $ex->getMessage() : '删除支付方式失败'];
        }
    }

    /**
     * 删除一个渠道.
     *
     *
     * @param $where
     *
     * @return array
     */
    public function delChannel($where)
    {
        Db::startTrans();
        try {
            $this->modelPayChannel->deleteInfo($where);
            action_log('删除', '删除支付渠道，ID：'.$where['id']);
            Db::commit();

            return ['code' => CodeEnum::SUCCESS, 'msg' => '删除渠道成功'];
        } catch (\Exception $ex) {
            Db::rollback();
            Log::error($ex->getMessage());

            return ['code' => CodeEnum::ERROR,  'msg' => config('app_debug') ? $ex->getMessage() : '删除渠道失败'];
        }
    }

    /**
     * 删除一个渠道账户.
     *
     *
     * @param $where
     *
     * @return array
     */
    public function delAccount($where)
    {
        Db::startTrans();
        try {
            $this->modelPayAccount->deleteInfo($where);
            action_log('删除', '删除支付渠道账户，ID：'.$where['id']);
            Db::commit();

            return ['code' => CodeEnum::SUCCESS, 'msg' => '删除渠道账户成功'];
        } catch (\Exception $ex) {
            Db::rollback();
            Log::error($ex->getMessage());

            return ['code' => CodeEnum::ERROR,  'msg' => config('app_debug') ? $ex->getMessage() : '删除渠道账户失败'];
        }
    }
}
